package edu.siu.math.egut.main;

import java.io.IOException;

import edu.siu.math.egut.io.Algorithms;
import edu.siu.math.egut.io.LiE;
import edu.siu.math.egut.io.OutputPref;
import edu.siu.math.egut.util.Group;
import edu.siu.math.egut.util.NonlinearException;
import edu.siu.math.egut.util.NotARootException;
import edu.siu.math.egut.util.Polynomial;
import edu.siu.math.egut.util.Unipotent;

public class Embedding {

    private static final String INSTRUCTIONS = "Input is:\n " +
    		"\t* a hand-typed list of roots for a unipotent element of the Levi\n" +
    		"\t* a hand-typed list of roots for U/(U,U).  (The embedding being calculated\n" +
    		"\t\tis sensitive to the order.)\n" +
    		"\t* the string you would use to describe the unipotent radical to LiE\n " +
    		"\t\t(e.g, \"1\" or \"[1,3]\"\n" +
    		"\t* the name of the group.";

    /**
     * 
     * 
     * @param args  String[]  there can be two or three.  
     * if two, should specify a parabolic an an exceptional group.  
     * if three, also specifies a subgroup of the levi. 
     */
    public static void main(String[] args) {
	
	if(args.length !=4){
	    System.out.println("This program needs 4 pieces of input."+INSTRUCTIONS);
	    System.exit(1);
	}
	Group g = Group.getGroup(args[args.length-1]);
	if( g== null){
	    System.out.println("Last argument should be the name of a simple exceptional group;\n \""+args[args.length-1]+"\" is not.\n"+INSTRUCTIONS);
	    System.exit(1);
	}
	LiE lie = new LiE();
	
	    try {
		int[][] uMat = Algorithms.readLiEMatrix(lie.exec("unipRad("+args[2]+","+args[3]+")", OutputPref.HIDE));
		int[][] uPiece1 =Algorithms.readHandTyped(args[1]);
		int[][] vMat = Algorithms.readHandTyped(args[0]);
	
		Unipotent u = new Unipotent(g,uMat, "u");
		Unipotent v = new Unipotent(g,vMat, "v");
		
		// compute v^{-1} u v.  
		
		Unipotent p = Unipotent.multiply(u,v);
		int next = p.indexOf(vMat);
		while (next != -1) {
		    p.pushFarLeftAndRemove(next);
		    next = p.indexOf(vMat);
		    
		}
		
		
		Polynomial[][] m = new Polynomial[uPiece1.length][uPiece1.length];
		StringBuilder result =new StringBuilder("{{");
		String[] us = new String[uPiece1.length];
		for( int i = 0; i < us.length; i++){
			us[i]=u.defaultString("u", uPiece1[i]);
			
		    
		}
		for( int i = 0; i < m.length; i++)
		    m[i]=p.get(p.indexOf(uPiece1[i])).getArgument().coefficients(us);
		
		// there is a problem with this program.  It computes a matrix using the 
		// F-basis x_{\alpha}(1).  But for half of all alpha it should be using 
		// x_{\alpha}( 1/N(\alpha', \alpha)).  
		
		// The matrix you really want is d^{-1} m d, 
		// where m is the matrix computed just above, and 
		// d = diag( 1, ... 1, N(alpha1, beta1), dots N( alpha n, beta n)),
		
		// Issue:  if N(\alpha', \alpha) is 2, will this take us outside the realm
		// of Polynomials with integral coefficients?
		// (I worked an example in which it somewhat miraculously did not..
		// is there a theorem there?)
		
		// Answer:  Write m = A & B\\ C &D.  (A,B,C,D being n x n) Conjugation by d leaves A unaffected
		// multiplies entries in B by integers.  Now assume that C= 0.  Then D = _tA^{-1},
		// where _t denotes lower transpose.  This means that means D has integral 
		// coefficients as well (?).  One easily constructs examples with nonintegral coefficients by 
		// taking C to be nonzero.  
		
		
		// TODO well worthwhile to have a functioning one that computes the desired
		// matrix just for unipotent elements of the Siegel.
		
		// eventually want to have functioning embedding program for general
		
		// TODO this program computes a matrix r(g) such that 
		// g^{-1} l^{-1}( x|y| z) g l( (x|y).r(g)|z)
		// where l: Y -> Heisenberg is an isomorphism.
		
		// TODO it would be nice to have a version where you set the basis and 
		// can then compute matrices of various elements without having to re-enter
		
		//TODO a sensible solution for a lot of these programs could be to have them read 
		// input from a plaintext file. then one can use one's preferred text editor to 
		// edit input.  
		
		
		for( int i = 0; i < m.length; i++){
		    for( int j = 0 ; j < m.length; j++){
			result = result.append(m[j][i].toString());
			if( j == m.length - 1){
			    if( i !=m.length-1)
				result.append("},{");
			}
			else
			    result.append(",");

		    }
		}
		result.append("}}");
		System.out.print(result.toString());
		
		
	    } catch (IOException e) {
		e.printStackTrace();
		System.exit(1);
	    } catch (NotARootException e) {
		e.printStackTrace();
		System.exit(1);
	    } catch (NonlinearException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    
	
    }

}
